#pragma once
#include <string>
#include <set>
#include <list>
#include <vector>
#include "TGameObject.h"
#include "Timer.h"
#include "ResMgr.h"

using std::string;
using std::set;
using std::vector;
using std::list;

 //<ParticleSystem Name = "Fire">
 //<count>100</count>
 //<lifetime>800</lifetime>
 //<colors>
 //   <color time = 50>255 255 255</color>
 //   <color time = 200>255 255 0 </color>
 //   <color time = 800>255 0 0 </color>
 //</colors>
 //<alphaChannel type="linear">
 //   <alpha time=50>255</alpha>
 //   <alpha time=300>0</alpha>
 //</alphaChannel>
 //<speeds>
 //   <speed time = 800>5</speed>
 //<speeds>
 //<images>
 //   <image>fire1</image>
 //   <image>fire2</image>
 //</images>
 //</ParticleSystem>

class IPoolItem
{
public:
    virtual void Reset() = 0;
    virtual void Free() = 0;
    virtual ~IPoolItem(){};
};
class Pool
{
    DWORD m_ActiveItems;
    vector<IPoolItem*> m_OriginalItems;
    vector<IPoolItem*> m_items;
public:
    Pool(vector<IPoolItem *> items)
    {
        m_items.insert(m_items.begin(), items.begin(), items.end());
        m_OriginalItems.insert(m_OriginalItems.begin(), items.begin(), items.end());
        m_ActiveItems = m_items.size();
    }

    virtual ~Pool()
    {    
        m_ActiveItems = 0;
        int len = m_OriginalItems.size();
        for (int i=0;i < len;i++)
        {
            delete m_OriginalItems[i];
        }
        m_items.clear();
    }

    IPoolItem* CreateObject()
    {
        if (!m_ActiveItems) return NULL;
        IPoolItem* item = m_items[m_ActiveItems-1];
        m_ActiveItems--;
        item->Reset();
        return item;
    }
    void FreeObject(IPoolItem* item)
    {
        item->Free();
        m_items[m_ActiveItems++] = item;
    }
};

class CParticleSystem
{    
    float m_Angle;
    int m_x;
    int m_y;
    BOOL m_bEnabled;
    int m_Count;    
    Timer m_TimerGenerateNew;
    DWORD m_dwTimeForCreateNew;
    DWORD m_dwLifeTime;

    typedef struct TIME
    {
        DWORD time;
        bool operator <(const TIME& b) const
        {
            return time < b.time;
        }
    }TIME;
    typedef struct RGB : public TIME
    {
        BYTE R;
        BYTE G;
        BYTE B;
    }RGB;
    typedef struct ALPHA : public TIME
    {
        BYTE Alpha;
    }ALPHA;
    typedef struct SPEED : public TIME
    {
        float Speed;
    }SPEED;

    set<RGB> m_ColorChanges;    
    set<ALPHA> m_AlphaChanges;   
    set<SPEED> m_SpeedChanges;    

    vector<TGDKImage*> m_lstUsedImages;    

    TGameObject *m_Object;

    class CElement : public IPoolItem
    {
        CParticleSystem* system;
        DWORD m_dwStartLive;        
        BOOL m_bActive;
        TGDKSprite *spr;
        float m_Angle;
        float m_SpeedValue;
        set<SPEED>::iterator m_CurrentSpeed;
        set<RGB>::iterator m_CurrentColor;
        set<RGB>::iterator m_NextColor;
        set<ALPHA>::iterator m_CurrentAlpha;
        set<ALPHA>::iterator m_NextAlpha;
    public:
        CElement(CParticleSystem* system);
        
        virtual ~CElement();;

        BOOL Update();

        virtual void Reset();

        virtual void Free();

    };
    list<CElement*> m_lstActiveElements;
    Pool *m_pool;    
    VOID ParseRGB( string content, RGB& rgb);
    void Cleanup();
    int GetX();
    int GetY();
public:
    CParticleSystem(string filename);
    void Attach(TGameObject *object);
    void Preload();
    void Start(int x, int y, float fAngle);
    void Update();
    void SetEnabled(BOOL bEnabled);
    void SetAngle(float fAngle);
    void SetTimeGeneration(DWORD time);
    virtual ~CParticleSystem(void);
};
